package cqrtplm.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.basic.util.TyplmEntityBaseUtil;
import com.hustcad.plm.pdm.classification.model.dto.TyplmClassificationEntityDTO;
import com.hustcad.plm.pdm.classification.service.TyplmClassificationService;
import com.hustcad.plm.pdm.common.model.vo.search.ResultEntityVO;
import com.hustcad.plm.pdm.common.service.search.TyplmCommonSearchService;
import com.hustcad.plm.pdm.doc.vo.DocDetails;
import com.hustcad.plm.pdm.enumeration.model.vo.EnumerationItemHandleVO;
import com.hustcad.plm.pdm.enumeration.service.TyplmEnumerationItemService;
import com.hustcad.plm.pdm.middle.partbom.service.TyplmPdmPartService;
import com.hustcad.plm.pdm.partbom.dto.InsertPartDTO;
import com.hustcad.plm.pdm.partbom.dto.PartBomTree;
import com.hustcad.plm.pdm.partbom.dto.PdmPartDescribeLinkDTO;
import com.hustcad.plm.pdm.partbom.dto.SimilarCreateDTO;
import com.hustcad.plm.pdm.partbom.service.TyplmPartBomService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartRelObjectService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartService;
import com.hustcad.plm.pdm.partbom.vo.MultilevelChildPartVO;
import com.hustcad.plm.pdm.partbom.vo.PartBomTreeByFilterVO;
import com.hustcad.plm.pdm.partbom.vo.PartDetailsVO;
import com.hustcad.plm.pdm.type.service.TyplmTypeService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.part.PartDO;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.vo.TyAttributeDefMapVO;
import cqrtplm.common.CommonService;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.constant.RTPlmConstant;
import cqrtplm.constant.RTTableTypeConstant;
import cqrtplm.dto.GenerateDescriptionRuleDto;
import cqrtplm.dto.UserQueryDTO;
import cqrtplm.entity.CodeDrawingDO;
import cqrtplm.entity.CodeMaterialDO;
import cqrtplm.entity.CodeStandardDO;
import cqrtplm.entity.DescribeSpliceRuleDO;
import cqrtplm.mapper.*;
import cqrtplm.service.CodeSequenceService;
import cqrtplm.service.FlowCodeService;
import cqrtplm.service.QueryPartService;
import cqrtplm.service.RTClassificationService;
import cqrtplm.util.SequenceGenerator;
import cqrtplm.vo.DescriptionVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CodeSequenceServiceImpl implements CodeSequenceService {
    private static final int MAX_RETRY = 150 ; //设置最大重试次数防止死循环
    private static final String MAP_SEPARATOR = "\\|";
    @Resource
    private CodeDrawingMapper codeDrawingMapper;
    @Resource
    private FlowCodeService flowCodeService;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private CodeMaterialMapper codeMaterialMapper;
    @Resource
    private TyplmPartBomService typlmPartBomService;
    @Resource
    private TyplmPdmPartService typlmPdmPartService;
    @Resource
    private TyplmPartRelObjectService typlmPartRelObjectService;
    @Resource
    private CommonService commonService;
    @Resource
    private RTPartMapper rtPartMapper;
    @Resource
    private RTClassificationService classificationService;
    @Resource
    private CodeStandardMapper codeStandardMapper;
    @Resource
    private TyplmPartService typlmPartService;
    @Resource
    private ProcessNumberMapper processNumberMapper;
    @Resource
    private TyplmEnumerationItemService typlmEnumerationItemService;
    @Resource
    private RTEnumMapper rtEnumMapper;
    @Resource
    private TyplmTypeService typlmTypeService;
    @Resource
    private QueryPartService queryPartService;
    @Resource
    private TyplmCommonSearchService typlmCommonSearchService;
    @Resource
    private TyplmClassificationService typlmClassificationService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String generateDrawingCode(CodeDrawingDO dto) {
        String drawingCode = "";
        String finalDrawingCode = "";
        CodeDrawingDO codeDrawingDO = codeDrawingMapper.selectCodeDrawing(dto);
        if(ObjectUtils.isNotEmpty(codeDrawingDO) && StringUtils.isNotBlank(
                codeDrawingDO.getFlowCode()) && !codeDrawingDO.getFlowCode().equals("null")){
            //获取下一个流水码
            String fix = dto.getClassificationId() + dto.getRemark() + dto.getDevelopmentOrder();
            int count = rtPartMapper.selectPartNumberCountByFixAndType(fix,"PatternCode");
            int index = SequenceGenerator.indexOfFlowCode(codeDrawingDO.getFlowCode());
            String nextFlowCode;
            if(count == index){
                nextFlowCode = SequenceGenerator.nextCodeOf(codeDrawingDO.getFlowCode());
            } else {
                nextFlowCode = "01";
            }
            drawingCode = buildDrawingCode(codeDrawingDO, nextFlowCode);
            //校验
            codeDrawingDO.setFlowCode(nextFlowCode);
            checkDrawingCodeIfValid(drawingCode,codeDrawingDO);
            TyplmEntityBaseUtil.fillCommonFieldForUpdate(codeDrawingDO);
            codeDrawingMapper.updateByPrimaryKeySelective(codeDrawingDO);
            finalDrawingCode = buildDrawingCode(codeDrawingDO, codeDrawingDO.getFlowCode());
        }else {
            //插入流水码
            dto.setOid(snowflakeIdComponent.getInstance().nextId());
            dto.setOtype(RTTableTypeConstant.TYPE_CODE_SEQUENCE_DRAWING);
            dto.setFlowCode("01");

            drawingCode = buildDrawingCode(dto, dto.getFlowCode());
            checkDrawingCodeIfValid(drawingCode,dto);

            TyplmEntityBaseUtil.fillCommonFieldForCreate(dto);
            codeDrawingMapper.insert(dto);
            finalDrawingCode = buildDrawingCode(dto, dto.getFlowCode());
        }
        log.info("生成DrawingCode:{}",finalDrawingCode);
        String code = finalDrawingCode.substring(finalDrawingCode.length() - 4, finalDrawingCode.length() - 2); // 11
         finalDrawingCode.substring(0, finalDrawingCode.length() - 4);
        return finalDrawingCode;
    }

    private void checkDrawingCodeIfValid(String drawingCode, CodeDrawingDO dto) {
        String nextFlowCode = dto.getFlowCode();
        int retryCount = 0;

        while (retryCount < MAX_RETRY) {
            List<PartDO> partDO = typlmPartService.queryPartByNumber(drawingCode.trim());
            if (CollUtil.isEmpty(partDO)) {
                break; // 找不到说明当前 drawingCode 可用
            }
            nextFlowCode = SequenceGenerator.nextCodeOf(nextFlowCode);
            drawingCode = buildDrawingCode(dto, nextFlowCode);
            retryCount++;
        }

        if (retryCount >= MAX_RETRY) {
            log.warn("超过最大重试次数仍未生成有效 drawingCode: {}", drawingCode);
            throw new RuntimeException("无法生成有效的 drawingCode");
        }
        // 最终将最新的流水号设置回 dto
        dto.setFlowCode(nextFlowCode);
    }

    private String buildDrawingCode(CodeDrawingDO dto, String flowCode) {
        return dto.getClassificationId() + dto.getRemark() + dto.getDevelopmentOrder() + flowCode + "10";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String generateMaterialCode(CodeMaterialDO dto) {
        String colorCode = dto.getMonochrome();
        // 如果有颜色码 则根据颜色码查询 // 如果无 则根据图号查询 按照时间从大到小
        if(ObjectUtils.isNotEmpty(colorCode)){
            CodeMaterialDO codeMaterialDO = codeMaterialMapper.selectCodeMaterialByColorCode(dto);
            if(ObjectUtils.isNotEmpty(codeMaterialDO) && StringUtils.isNotBlank(
                    codeMaterialDO.getFlowCode()) && !codeMaterialDO.getFlowCode().equals("null")){
                //获取下一个流水码
                String fix = codeMaterialDO.getDrawingCode() + "-" + codeMaterialDO.getMonochrome();
                int count = rtPartMapper.selectPartNumberCountByFixAndType2(fix,"MaterialCode");
                int index = SequenceGenerator.indexOfFlowCode(codeMaterialDO.getFlowCode());
                String nextFlowCode;
                if(count == index){
                    nextFlowCode = SequenceGenerator.nextCodeOf(codeMaterialDO.getFlowCode());
                } else {
                    nextFlowCode = "00";
                }
                //更新流水码
                codeMaterialDO.setFlowCode(nextFlowCode);
                String materialCode = codeMaterialDO.getDrawingCode() + "-" + codeMaterialDO.getMonochrome() + nextFlowCode;
                checkMaterialCodeIfValid(materialCode,codeMaterialDO);
                TyplmEntityBaseUtil.fillCommonFieldForUpdate(codeMaterialDO);
                codeMaterialMapper.updateByPrimaryKeySelective(codeMaterialDO);
                return codeMaterialDO.getDrawingCode() + "-" + codeMaterialDO.getMonochrome() + codeMaterialDO.getFlowCode();
            }else {
                //插入流水码
                dto.setOid(snowflakeIdComponent.getInstance().nextId());
                dto.setOtype(RTTableTypeConstant.TYPE_CODE_SEQUENCE_DRAWING);
                dto.setFlowCode("00");
                TyplmEntityBaseUtil.fillCommonFieldForCreate(dto);
                String materialCode = dto.getDrawingCode() + "-" + dto.getMonochrome() + dto.getFlowCode();
                checkMaterialCodeIfValid(materialCode,dto);
                codeMaterialMapper.insert(dto);
                return dto.getDrawingCode() + "-" + dto.getMonochrome() + dto.getFlowCode();
            }
        } else {
            CodeMaterialDO codeMaterialDO = codeMaterialMapper.selectCodeMaterialByDrawingCode(dto);
            if(ObjectUtils.isNotEmpty(codeMaterialDO)){
                //获取下一个流水码
                String fix = codeMaterialDO.getDrawingCode() + "-" + codeMaterialDO.getCompositeColor();
                int count = rtPartMapper.selectPartNumberCountByFixAndType2(fix,"MaterialCode");
                int index = SequenceGenerator.indexOfFlowCode(codeMaterialDO.getFlowCode());
                String flowCode;
                if(count == index){
                    flowCode = SequenceGenerator.nextCodeOf(codeMaterialDO.getFlowCode());
                } else {
                    flowCode = "00";
                }
                codeMaterialDO.setFlowCode(flowCode);

                //更新流水码
                String materialCode = codeMaterialDO.getDrawingCode() + "-" + codeMaterialDO.getCompositeColor() + codeMaterialDO.getFlowCode();
                checkMaterialCodeIfValid2(materialCode,codeMaterialDO);
                TyplmEntityBaseUtil.fillCommonFieldForUpdate(codeMaterialDO);
                codeMaterialMapper.updateByPrimaryKeySelective(codeMaterialDO);
                return codeMaterialDO.getDrawingCode() + "-" + codeMaterialDO.getCompositeColor() + codeMaterialDO.getFlowCode();
            }else {
                //插入流水码
                dto.setOid(snowflakeIdComponent.getInstance().nextId());
                dto.setOtype(RTTableTypeConstant.TYPE_CODE_SEQUENCE_DRAWING);
                CodeMaterialDO lastedCompositeColor = codeMaterialMapper.getLastedCompositeColor(dto.getDrawingCode());
                String colorFlowCode = "";
                if(ObjectUtils.isEmpty(lastedCompositeColor)){
                    colorFlowCode = "10";
                }else {
                    colorFlowCode = flowCodeService.getNextColorCode(lastedCompositeColor.getCompositeColor());
                }
                dto.setCompositeColor(colorFlowCode);
                String materialCode = dto.getDrawingCode() + "-" + dto.getCompositeColor() + "00";
                checkMaterialCodeIfValid2(materialCode,dto);
                TyplmEntityBaseUtil.fillCommonFieldForCreate(dto);
                codeMaterialMapper.insert(dto);
                return dto.getDrawingCode() + "-" + colorFlowCode + dto.getFlowCode();
            }
        }
    }
    private void checkMaterialCodeIfValid2(String drawingCode, CodeMaterialDO dto) {
        String nextFlowCode = dto.getFlowCode();
        int retryCount = 0;

        while (retryCount < MAX_RETRY) {
            List<PartDO> partDO = typlmPartService.queryPartByNumber(drawingCode.trim());
            if (CollUtil.isEmpty(partDO)) {
                break; // 找不到说明当前 drawingCode 可用
            }
            nextFlowCode = SequenceGenerator.nextCodeOf(nextFlowCode);
            drawingCode = dto.getDrawingCode() + "-" + dto.getCompositeColor() + nextFlowCode;
            retryCount++;
        }

        if (retryCount >= MAX_RETRY) {
            log.warn("超过最大重试次数仍未生成有效 drawingCode: {}", drawingCode);
            throw new RuntimeException("无法生成有效的 drawingCode");
        }
        // 最终将最新的流水号设置回 dto
        dto.setFlowCode(nextFlowCode);
    }

    private void checkMaterialCodeIfValid(String drawingCode, CodeMaterialDO dto) {
        String nextFlowCode = dto.getFlowCode();
        int retryCount = 0;

        while (retryCount < MAX_RETRY) {
            List<PartDO> partDO = typlmPartService.queryPartByNumber(drawingCode.trim());
            if (CollUtil.isEmpty(partDO)) {
                break; // 找不到说明当前 drawingCode 可用
            }
            nextFlowCode = SequenceGenerator.nextCodeOf(nextFlowCode);
            drawingCode = dto.getDrawingCode() + "-" + dto.getMonochrome() + nextFlowCode;
            retryCount++;
        }

        if (retryCount >= MAX_RETRY) {
            log.warn("超过最大重试次数仍未生成有效 drawingCode: {}", drawingCode);
            throw new RuntimeException("无法生成有效的 drawingCode");
        }
        // 最终将最新的流水号设置回 dto
        dto.setFlowCode(nextFlowCode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void drawingCodeUpgraded(String drawingCode) {
        // 获取图号衍生出的所有物料码
        PartDO partDO1 = rtPartMapper.queryLatestPartByNumberAndView(drawingCode, RTPlmConstant.VIEW_DESIGN, "");
        if(ObjectUtils.isEmpty(partDO1)){
            return;
        }else {
            String lifecyclestagekey = partDO1.getLifecyclestagekey();
            List<String> lifeStageKeys = Arrays.asList("RELEASED", "EffectiveNot");
            if(!lifeStageKeys.contains(lifecyclestagekey)){
                throw RTErrorCodeEnum.DRAWING_CODE_NAME_ERROR.getException("请重新选择“已生效”或“生效未出图”的图样代号！");
            }
        }
        List<String> types = Arrays.asList("PatternCode", "MaterialCode");
        List<PartDO> partDOS = rtPartMapper.getAllRelevancyPart(drawingCode, types);//100
        if (CollUtil.isEmpty(partDOS)) {
            return;
        }

        // 判断当前选择的待升版 图样代号 是否为最大流水编号
        List<String> patternCodeList = rtPartMapper.getMaxPatternCodePart(drawingCode.substring(0,11));
        if (log.isInfoEnabled()){
            log.info("patternCodeList===>{}",patternCodeList.toString());
        }
        String maxPatternCodePartPartnumber = "";
        //maxPatternCodePartPartnumber = Collections.max(patternCodeList);
        // 有效状态的图样代号
        int tydh = 0;
        // 图样代号应该只存在一个有效状态
        for (String s : patternCodeList) {
            String nextVersionCode = getNextVersionCode(s);
            if (!patternCodeList.contains(nextVersionCode)) {
                maxPatternCodePartPartnumber = s;
            }
            String lifecyclestagekey = typlmPartService.queryPartByNumber(s).get(0).getLifecyclestagekey();
            if ("RELEASED".equalsIgnoreCase(lifecyclestagekey) || "EffectiveNot".equalsIgnoreCase(lifecyclestagekey)) {
                tydh += 1;
            }
        }
        if (log.isInfoEnabled()){
            log.info("===>{}最大号：{}",drawingCode,maxPatternCodePartPartnumber);
        }
        if (!StringUtils.equals(maxPatternCodePartPartnumber,drawingCode)){
            throw RTErrorCodeEnum.DRAWING_CODE_NAME_ERROR.getException("当前选择不是最新图样代号，请基于["+maxPatternCodePartPartnumber+"]升级。");
        } else {
            if (tydh > 1){
                throw RTErrorCodeEnum.DRAWING_CODE_NAME_ERROR.getException("图样代号存在多个生效版本，请检查。");
            }
        }

        //失效
//        List<EntityLifeCycleDTO> entityLifeCycleDTOS = new ArrayList<>();
        for (PartDO partDO : partDOS) {
//            EntityLifeCycleDTO entityLifeCycleDTO = new EntityLifeCycleDTO();
//            entityLifeCycleDTO.setOid(partDO.getOid());
//            entityLifeCycleDTO.setOtype("ty.inteplm.part.CTyPart");
//            entityLifeCycleDTO.setLifeCycleStageKey("DISABLED");
//            entityLifeCycleDTOS.add(entityLifeCycleDTO);

            PartDetailsVO detailsVO = typlmPdmPartService.queryPartDetailsForCO(partDO.getOid(),
                                                                                TableTypeConstrant.TY_PART_OTYPE);
            List<DocDetails> docDetails = typlmPartRelObjectService.queryPartRelatedDocInfo(partDO.getOid());
            List<BigInteger> cadOidList = new ArrayList<>();
            if (CollUtil.isNotEmpty(docDetails)) {
                cadOidList = docDetails.stream().map(item -> new BigInteger(item.getOid())).collect(
                        Collectors.toList());
            }
            List<PdmPartDescribeLinkDTO> docList = getDocList(detailsVO.getOid());
            List<MultilevelChildPartVO> childPartList = getChildPartList(detailsVO.getObjectNumber(),
                                                                         detailsVO.getOid(),
                                                                         detailsVO.getView());
            SimilarCreateDTO similarCreateDTO = buildSimilarCreateParam(detailsVO, cadOidList, docList,
                                                                        childPartList, drawingCode);
            // 判断新物料是否存在
            /*PartDO partDO2 = typlmPdmPartService.queryLastPartDoByPartNumber(similarCreateDTO.getInsertPartDTO().getPartNumber());
            if (partDO2 != null) {
                throw RTErrorCodeEnum.DRAWING_CODE_NAME_ERROR.getException("升版后的对象已存在，请重新选择！");
            }*/

            typlmPartBomService.similarCreate(similarCreateDTO);
        }
//        if(!entityLifeCycleDTOS.isEmpty()){
//            typlmLifecycleTemplateService.batchUpdateEntityLifecycle(entityLifeCycleDTOS, false, false, false);
//        }
    }

    private List<PdmPartDescribeLinkDTO> getDocList(String oid) {
        List<PdmPartDescribeLinkDTO> docList = new ArrayList<>();
        List<DocDetails> partLinkReferenceDoc = typlmPdmPartService.getPartLinkReferenceDoc(oid);
        for (DocDetails docDetails : partLinkReferenceDoc) {
            PdmPartDescribeLinkDTO pdmPartDescribeLinkDTO = new PdmPartDescribeLinkDTO();
            pdmPartDescribeLinkDTO.setBoid(docDetails.getOid());
            pdmPartDescribeLinkDTO.setName(docDetails.getName());
            docList.add(pdmPartDescribeLinkDTO);
        }
        return docList;
    }

    private List<MultilevelChildPartVO> getChildPartList(String partNumber, String partOid, String view) {
        List<MultilevelChildPartVO> list = new ArrayList<>();
        PartBomTreeByFilterVO partBomTreeByFilterVO = commonService.queryChildPartsNoIba(partNumber, partOid, view,
                                                                                         false, "", "N", false);
        List<PartBomTree> partBomTreeList = partBomTreeByFilterVO.getPartBomTreeList();
        partBomTreeList.remove(0);
        for (PartBomTree partBomTree : partBomTreeList) {
            MultilevelChildPartVO multilevelChildPartVO = new MultilevelChildPartVO();
            multilevelChildPartVO.setMasterID(partBomTree.getMasteredoid());
            multilevelChildPartVO.setParentPartOid(partOid);
            list.add(multilevelChildPartVO);
        }
        return list;
    }

    /**
     * 构建类似创建参数
     *
     * @param detailsVO
     * @param cadOidList
     * @return {@link SimilarCreateDTO }
     */
    private SimilarCreateDTO buildSimilarCreateParam(PartDetailsVO detailsVO, List<BigInteger> cadOidList,List<PdmPartDescribeLinkDTO> docList,List<MultilevelChildPartVO> childPartList,String drawingCode) {
        SimilarCreateDTO similarCreateDTO = new SimilarCreateDTO();
        similarCreateDTO.setCadIdList(cadOidList);
        similarCreateDTO.setFatherOid(new BigInteger(detailsVO.getOid()));
        similarCreateDTO.setFatherOtype(TableTypeConstrant.TY_PART_OTYPE);
        similarCreateDTO.setIsNeedQueryChild(true);
        similarCreateDTO.setFatherViewName(detailsVO.getPartView());
        similarCreateDTO.setChildPartList(childPartList);
        similarCreateDTO.setDocList(docList);
        InsertPartDTO insertPartDTO = new InsertPartDTO();
        insertPartDTO.setFolderId(detailsVO.getFolderId().toString());
        insertPartDTO.setFolderPath(detailsVO.getFolderPath());
        insertPartDTO.setContainerID(detailsVO.getContaineroid());
        insertPartDTO.setContainerType(detailsVO.getContainerotype());
        insertPartDTO.setContainerName(detailsVO.getContainerName());
        insertPartDTO.setTypeOid(detailsVO.getTypeOid());
        insertPartDTO.setClassId(detailsVO.getClassId());
        insertPartDTO.setProductID(detailsVO.getContaineroid());
        insertPartDTO.setTypeOType(detailsVO.getTypeOtype());
        insertPartDTO.setPartView(detailsVO.getPartView());
        insertPartDTO.setPartNumber(getNextNumber(detailsVO.getObjectNumber(),drawingCode));
        insertPartDTO.setLifecycleTemplateID(new BigInteger(detailsVO.getLifecycleTemplateID()));
        insertPartDTO.setName(detailsVO.getName());
        insertPartDTO.setGenericType(detailsVO.getGenericType());
        insertPartDTO.setSource(detailsVO.getSource());
        insertPartDTO.setEnditem(0L);
        insertPartDTO.setAssemblyMode(detailsVO.getAssemblyMode());
        insertPartDTO.setUnit(detailsVO.getUnit());
        insertPartDTO.setPhantom(detailsVO.getPhantom().toString());
        insertPartDTO.setSecuritylabels(detailsVO.getSecurity());
        insertPartDTO.setLifecycleTemplate(detailsVO.getLifecycleMasterName());
        insertPartDTO.setLifecycleTemplateID(new BigInteger(detailsVO.getLifecycleTemplateID()));
        insertPartDTO.setLifecycleState("Creating");
        insertPartDTO.setDescription(detailsVO.getDescription());
        Map<String, List<String>> ibaAttributeMap = detailsVO.getIbaAttributeMap();
        ibaAttributeMap.put("isSimilarCreate", Collections.singletonList("true"));
        insertPartDTO.setIbaAttribute(new LinkedHashMap<>(ibaAttributeMap));
        similarCreateDTO.setInsertPartDTO(insertPartDTO);
        return similarCreateDTO;
    }

    private String getNextNumber(String objectNumber,String drawingCode) {
        if(objectNumber.equals(drawingCode)){
            return getNextVersionCode(drawingCode);
        }else if(objectNumber.contains(drawingCode)){
            String newDrawingCode = getNextVersionCode(drawingCode);
            return objectNumber.replace(drawingCode,newDrawingCode);
        }else {
            throw RTErrorCodeEnum.DRAWING_CODE_NAME_ERROR.getException("图样代号参数异常");
        }
    }

    public String getNextVersionCode (String drawingCode ){
        String left = drawingCode.substring(0, 11);
        String next = SequenceGenerator.nextCodeOf(drawingCode.substring(11));
        return left+next;
    }

    @Override
    public DescriptionVO generateDescriptionRule(GenerateDescriptionRuleDto dto, Boolean remark) {
        String classId = dto.getClassId();
        if(classId == null){
            throw RTErrorCodeEnum.DESCRIBE_RULE_ERROR.getException("参数异常,classId不存在!!");
        }
        String typeOtype = dto.getType();
        if (typeOtype == null) {
            throw RTErrorCodeEnum.DESCRIBE_RULE_ERROR.getException("参数异常,typeOtype不存在!!");
        }
        Map<String, List<String>> map = dto.getIbaMap();
        if ("true".equals(dto.getIsMaterial())) {
            TyplmClassificationEntityDTO currentClassInfo = typlmClassificationService.queryClassificationDTOByOID(new BigInteger(classId));
            classId = currentClassInfo.getParentOid();
        }
        IdentifierEntity entity = new IdentifierEntity();
        entity.setOid(new BigInteger(classId));
        entity.setOtype("ty.inteplm.type.CTyClassification");
        DescribeSpliceRuleDO describeSpliceRuleDO = classificationService.queryAttrDescribeRule(entity);
        if (describeSpliceRuleDO == null) {
            throw RTErrorCodeEnum.DESCRIBE_RULE_ERROR.getException("当前属性卡牌描述规则不存在,请检查描述规则");
        }

        String describeRules = describeSpliceRuleDO.getDescribeRules();
        ObjectMapper objectMapper = new ObjectMapper();
        String notSplicingAttrAndValue = describeSpliceRuleDO.getNotSplicingAttrAndValue();
        List<LinkedHashMap<String, String>> listMap;
        try {
            listMap = objectMapper.readValue(notSplicingAttrAndValue, new TypeReference<List<LinkedHashMap<String, String>>>() {});
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        String[] ibaInNames = describeRules.split("_");
        String[] ibaDisNames = describeSpliceRuleDO.getDisplayRules().split("_");
        Map<String, String> ibaMap = new HashMap<>();
        if(ibaInNames.length != ibaDisNames.length){
            throw RTErrorCodeEnum.DESCRIBE_RULE_ERROR.getException("描述规则维护错误，请检查描述规则");
        } else{
            for (int i = 0; i < ibaInNames.length; i++) {
                ibaMap.put(ibaInNames[i],ibaDisNames[i]);
            }
        }
        StringBuffer systemDescribe = new StringBuffer();
        StringBuffer ibaDescribe = new StringBuffer();
//        if(map.containsKey("13854")){
//            List<String> gb = map.get("13854");//国标码
//            if(CollUtil.isNotEmpty(gb) && StringUtils.isNotEmpty(gb.get(0))){
//                systemDescribe.append(gb.get(0)).append("_");
//                ibaDescribe.append(gb.get(0)).append("_");
//            }
//        }
        List<String> ibaNotExist = new ArrayList<>();
        List<String> ibaNotValue = new ArrayList<>();
        List<TyAttributeDefMapVO> tyAttributeDefMapVOS = typlmTypeService.queryInheritAttrDef(
                new BigInteger(classId), TableTypeConstrant.TY_CLASSIFICATION_OTYPE);
        List<BigInteger> attrLinkOid = tyAttributeDefMapVOS.stream().map(TyAttributeDefMapVO::getOid).collect(
                Collectors.toList());
        List<JSONObject> attrLinkEnumList = rtEnumMapper.selectClassIbaEnum(attrLinkOid);
        Map<String, String> attrLinkEnumMap = attrLinkEnumList.stream().collect(
                Collectors.toMap(
                        item -> item.getString("NAME"),
                        item -> item.getString("ENUMERATIONDEFOID"),
                        (existing, replacement) -> existing
                )
        );

        for (String iba : ibaInNames) {
            if (!map.containsKey(iba)) {
                ibaNotExist.add(ibaMap.get(iba));
                continue;
            }
            if("CertificationRequire".equals(iba)){
                log.error("属性值为空");
            }
            List<String> ibaValueList = map.get(iba);
            if (ibaValueList == null) {
                ibaValueList = Collections.emptyList();
            }

            boolean flag = true;
            if (!ibaValueList.isEmpty()) {
                for (Map<String, String> notSplitMap : listMap) {
                    if (notSplitMap.containsKey(iba)) {
                        // 过滤出非空且不是当前属性名的键
                        List<String> valueKeys = notSplitMap.keySet().stream()
                                .filter(Objects::nonNull)
                                .filter(key -> !key.isEmpty() && !key.equals(iba))
                                .collect(Collectors.toList());

                        // 如果没有其他键（只有属性名）或者包含当前属性值，则不拼接
                        if (valueKeys.isEmpty()) {
                            flag = false;
                            break;
                        } else {
                            // 检查ibaValueList中的任何值是否在notSplitMap中作为键存在
                            boolean valueMatched = ibaValueList.stream()
                                    .filter(Objects::nonNull)
                                    .anyMatch(notSplitMap::containsKey);

                            if (valueMatched) {
                                flag = false;
                                break;
                            }
                        }
                    }
                }
            }

            // 处理枚举值转换
            if (attrLinkEnumMap.containsKey(iba)) {
                String enumOid = attrLinkEnumMap.get(iba);
                if (!"0".equalsIgnoreCase(enumOid)) {
                    List<EnumerationItemHandleVO> enumerationItemHandleVOS = typlmEnumerationItemService.queryEnumerationItemByDefOid(
                            new IdentifierEntity(new BigInteger(enumOid), ""));
                    Map<String, String> enumValueMap = enumerationItemHandleVOS.stream().collect(Collectors.toMap(
                            EnumerationItemHandleVO::getName,
                            EnumerationItemHandleVO::getDisplayName,
                            (v1, v2) -> v1
                    ));

                    // 转换ibaValueList中的值
                    List<String> convertedValues = ibaValueList.stream()
                            .filter(Objects::nonNull)
                            .map(value -> enumValueMap.getOrDefault(value, value))
                            .collect(Collectors.toList());

                    // 使用转换后的值进行后续处理
                    String ibaValue = String.join(",", convertedValues); // 如果需要将列表转换为字符串

                    if (flag) {
                        ibaDescribe.append(ibaValue).append("_");
                    }
                    if (!convertedValues.isEmpty() && convertedValues.stream().noneMatch(StringUtils::isBlank)) {
                        systemDescribe.append(ibaValue).append("_");
                    } else {
                        ibaNotValue.add(ibaMap.get(iba));
                    }
                }
            } else {
                // 无需处理枚举属性
                String ibaValue = String.join(",", ibaValueList);
                if (flag) {
                    ibaDescribe.append(ibaValue).append("_");
                }
                if (StringUtils.isNotEmpty(ibaValue) && StringUtils.isNotBlank(ibaValue)) {
                    systemDescribe.append(ibaValue).append("_");
                } else {
                    ibaNotValue.add(ibaMap.get(iba));
                }
            }
        }
        if(CollUtil.isNotEmpty(ibaNotExist)){
            throw RTErrorCodeEnum.DESCRIBE_RULE_ERROR.getException("生成描述规则维护错误,属性:" + ibaNotExist + "在当前属性卡片这不存在");
        }
        if(CollUtil.isNotEmpty(ibaNotValue)){
            throw RTErrorCodeEnum.DESCRIBE_RULE_ERROR.getException("生成描述规则维护错误,属性:" + ibaNotValue + "值为空,请维护这些属性");
        }
        if (systemDescribe.length() > 0 && systemDescribe.charAt(systemDescribe.length() - 1) == '_') {
            systemDescribe.deleteCharAt(systemDescribe.length() - 1);
        }
        if (ibaDescribe.length() > 0 && ibaDescribe.charAt(ibaDescribe.length() - 1) == '_') {
            ibaDescribe.deleteCharAt(ibaDescribe.length() - 1);
        }
        if(StringUtils.isBlank(dto.getIsCheckCurrentDescriptionIfExist())){
            //检查描述规则是否存在
            List<String> list;
            if (map.containsKey("PatternCodeDescription")) {
                // 包含图样代号描述
                List<String> patternCodeDescription = map.get("PatternCodeDescription");
                String materialDescribe = String.join(",",patternCodeDescription) + ";" + systemDescribe;
                list = checkCurrentDescriptionIfExist(RTPlmConstant.IBA_MATERIALCODEDESCRIPTION , materialDescribe, typeOtype);
            } else if (map.containsKey("Common_Attributes|1757215074349")) {
                list = checkCurrentDescriptionIfExist(RTPlmConstant.IBA_MATERIALCODEDESCRIPTION , String.valueOf(systemDescribe), typeOtype);
            } else {
                list = checkCurrentDescriptionIfExist(RTPlmConstant.IBA_COMPLETEDESCRIPTION , String.valueOf(systemDescribe), typeOtype);
            }
            if (CollUtil.isNotEmpty(list) && remark) {
                throw RTErrorCodeEnum.DESCRIBE_RULE_ERROR.getException(
                        "描述生成失败，该描述:"+systemDescribe+",与编码为:" + list + "的零部件描述一致");
            }
        }

        DescriptionVO descriptionVO = new DescriptionVO();
        descriptionVO.setSystemDescription(systemDescribe.toString());
        descriptionVO.setIbaDescription(ibaDescribe.toString());
        return descriptionVO;
    }

    public List<String> checkCurrentDescriptionIfExist(String ibaAttrName,String systemDescribe, String typeName) {
        UserQueryDTO userQueryDTO = new UserQueryDTO();
        UserQueryDTO.ConditionGroup conditionGroup = new UserQueryDTO.ConditionGroup();
        UserQueryDTO.Condition condition = new UserQueryDTO.Condition();
        condition.setOperator("equals");
        condition.setValue(systemDescribe);
        conditionGroup.setLogic("and");
        conditionGroup.setConditions(Collections.singletonList(condition));
        userQueryDTO.setConditions(Collections.singletonMap(ibaAttrName.toLowerCase(), conditionGroup));
        userQueryDTO.setPageSize(1);
        userQueryDTO.setPageNum(1);
        if(!typeName.contains("|")){
            typeName = TableTypeConstrant.TY_PART_OTYPE + "|" + typeName;
        }
        userQueryDTO.setTypeInthid(typeName);
        userQueryDTO.setIsQueryDTO("1");
        PageInfo<ResultEntityVO> resultEntityVOPageInfo = queryPartService.queryPartData(userQueryDTO, Boolean.FALSE);
        List<ResultEntityVO> list = resultEntityVOPageInfo.getList();
        if(CollUtil.isNotEmpty(list)){
            return list.stream().map(ResultEntityVO::getObjectNumber).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String generateStandardCode(String classCode, Map<String, String> ibaMap) {
        String finalStandardCode = "";
        StringBuilder standardCode = new StringBuilder();
        standardCode.append(classCode).append("-");

        // 拼接基础编码
        appendWithDefault(standardCode, ibaMap.get("specification"), 4); // 规格取前4位
        appendCharIfPresent(standardCode, ibaMap.get("screwPitch"), "螺距(screwPitch)"); // 首字符
        appendCharIfPresent(standardCode, ibaMap.get("performance"), "性能(performance)"); // 性能首字符
        appendCharIfPresent(standardCode, ibaMap.get("surfaceTreatment"), "表面处理(surfaceTreatment)"); // 表面处理首字符

        String hazardousSubstance = ibaMap.get("hazardousSubstance"); // 有害物质
        String specialRequirement = ibaMap.get("specialRequirement"); // 特殊要求

        if ("无".equals(hazardousSubstance) && "无".equals(specialRequirement)) {
            return String.valueOf(standardCode);
        }

        String baseCode = String.valueOf(standardCode);
        CodeStandardDO codeStandardDO = codeStandardMapper.selectCodeStandardByFix(baseCode);

        if(ObjectUtils.isNotEmpty(codeStandardDO) && StringUtils.isNotBlank(
                codeStandardDO.getFlowCode()) && !codeStandardDO.getFlowCode().equals("null")){
            //获取下一个流水码
            String finalNextFlowCode = SequenceGenerator.nextCodeOf(codeStandardDO.getFlowCode());
            finalStandardCode = checkStandardCodeIfValid(baseCode, finalNextFlowCode);

            //更新流水码
            String finalFlowCode = finalStandardCode.substring(finalStandardCode.length() - 2);
            codeStandardDO.setFlowCode(finalFlowCode);
            TyplmEntityBaseUtil.fillCommonFieldForUpdate(codeStandardDO);
            codeStandardMapper.updateByPrimaryKeySelective(codeStandardDO);
        }else {
            String initialFlowCode = "00";
            finalStandardCode = checkStandardCodeIfValid(String.valueOf(standardCode), initialFlowCode);

            codeStandardDO = new CodeStandardDO();
            codeStandardDO.setOid(snowflakeIdComponent.getInstance().nextId());
            codeStandardDO.setOtype(RTTableTypeConstant.TYPE_CODE_SEQUENCE_DRAWING);
            String finalFlowCode = finalStandardCode.substring(finalStandardCode.length() - 2);
            codeStandardDO.setFlowCode(finalFlowCode);
            codeStandardDO.setFix(baseCode);
            TyplmEntityBaseUtil.fillCommonFieldForCreate(codeStandardDO);
            codeStandardMapper.insert(codeStandardDO);
        }

        return finalStandardCode;
    }

    private void appendWithDefault(StringBuilder sb, String value, int length) {
        if (value != null) {
            sb.append(value.length() >= length ? value.substring(0, length) : value);
        }else {
            throw RTErrorCodeEnum.GENERATE_CODE_ERROR.getException("生成标准编码失败,属性规格(specification)为空" );
        }
    }

    private void appendCharIfPresent(StringBuilder sb, String value, String key) {
        if (value != null && !value.isEmpty()) {
            sb.append(value.charAt(0));
        } else {
            throw RTErrorCodeEnum.GENERATE_CODE_ERROR.getException("生成标准编码失败,属性"+ key + "为空" );
        }
    }

    private String checkStandardCodeIfValid(String fix,String flowCode) {
        int retryCount = 0;
        String currentFlowCode = flowCode;
        while (retryCount < MAX_RETRY) {
            String standardCode = fix + currentFlowCode;
            PartDO partDO = rtPartMapper.queryLatestPartByNumberAndView(standardCode.trim(), RTPlmConstant.VIEW_DESIGN, "");
            if (ObjectUtils.isEmpty(partDO)) {
                return standardCode;
            }
            currentFlowCode = String.format("%02d", Integer.parseInt(currentFlowCode) + 1);
            retryCount++;
        }
        throw RTErrorCodeEnum.GENERATE_CODE_ERROR.getException("生成标准编码失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String generateEBOMCode(String devOrder) {
        CodeStandardDO codeStandardDO = codeStandardMapper.selectCodeStandardByFix(devOrder);
        String finalEbomCode = "";
        if(ObjectUtils.isNotEmpty(codeStandardDO) && StringUtils.isNotBlank(
                codeStandardDO.getFlowCode()) && !codeStandardDO.getFlowCode().equals("null")){

            //获取下一个流水码
            Integer nextFlowCode = Integer.parseInt(codeStandardDO.getFlowCode())+1;
            String formattedFlowCode = String.format("%05d", nextFlowCode);
            finalEbomCode = checkEBOMCodeIfValid(devOrder, formattedFlowCode);

            //更新流水码
            codeStandardDO.setFlowCode(finalEbomCode.substring(finalEbomCode.length() - 5));
            TyplmEntityBaseUtil.fillCommonFieldForUpdate(codeStandardDO);
            codeStandardMapper.updateByPrimaryKeySelective(codeStandardDO);
        }else {
            //插入流水码
            finalEbomCode = checkEBOMCodeIfValid(devOrder, "00000");

            codeStandardDO = new CodeStandardDO();
            codeStandardDO.setOid(snowflakeIdComponent.getInstance().nextId());
            codeStandardDO.setOtype(RTTableTypeConstant.TYPE_CODE_SEQUENCE_DRAWING);
            codeStandardDO.setFlowCode(finalEbomCode.substring(finalEbomCode.length() - 5));
            codeStandardDO.setFix(devOrder);
            TyplmEntityBaseUtil.fillCommonFieldForCreate(codeStandardDO);
            codeStandardMapper.insert(codeStandardDO);
        }

        return finalEbomCode;
    }

    private String checkEBOMCodeIfValid(String devOrder,String flowCode) {
        int retryCount = 0;
        final int MAX_RETRY = 99999;
        String currentFlowCode = flowCode;
        while (retryCount < MAX_RETRY) {
            String ebomCode = devOrder + currentFlowCode;
            PartDO partDO = rtPartMapper.queryLatestPartByNumberAndView(ebomCode.trim(), RTPlmConstant.VIEW_DESIGN, "");
            if (ObjectUtils.isEmpty(partDO)) {
                return ebomCode;
            }
            currentFlowCode = String.format("%05d", Integer.parseInt(currentFlowCode) + 1);
            retryCount++;
        }
        throw RTErrorCodeEnum.GENERATE_CODE_ERROR.getException("无法生成有效的 EBOM 编码");
    }

    @Override
    public String generateProcessCode() {
        return processNumberMapper.generateProcessCode();
    }

    @Override
    public String selectCategoryCodeByClassId(BigInteger classId) {
        List<String> v = processNumberMapper.selectCategoryCodeByClassId(classId);
        if(CollUtil.isNotEmpty(v)){
            if (v.size()==1){
                return v.get(0);
            }
            throw RTErrorCodeEnum.GENERATE_CODE_ERROR.getException("该分类下存在多个属性卡片的品类码不相同:"+classId);
        }
        throw RTErrorCodeEnum.GENERATE_CODE_ERROR.getException("该分类未找到到属性卡片:"+classId);
    }

}
